package bu.met.cs664;

import java.util.Arrays;

/**
 * Abstract class to identify players and to make sure they are capable of making a move.
 */
public abstract class Player {
	private int[] startPosition;
	private int[] currentPosition;
	private boolean hasGold;
	private boolean hasArrow;
	private boolean hitWumpus;
	
	/**
	 * Constructor
	 * 
	 * @param position	The square where the player is originally placed
	 */
	public Player(int[] position) {
		startPosition = position;
		currentPosition = startPosition.clone();
		hasGold = false;
		hasArrow = true;
		hitWumpus = false;
	}
	
	int[] getPosition() {
		return currentPosition.clone();
	}
	
	int[] getStartPosition() {
		return startPosition.clone();
	}
	
	boolean hasGold() {
		return hasGold;
	}
	
	boolean hasArrow() {
		return hasArrow;
	}
	
	/**
	 * Get the next position where this player will go.
	 * 
	 * @param board	the board that the player is moving on
	 * 
	 * @return	an array with the x,y coordinates of the position or null if left
	 */
	public int[] nextMove(Board board) {
		while (true) {
			String attributes = board.getState(currentPosition);
			
			if (hitWumpus) {
				attributes = attributes + "M";
				hitWumpus = false;
			}
			
			Actions key = getAction(attributes);
			
			int[] position = currentPosition.clone();
			boolean isStartPosition = Arrays.equals(position, startPosition);
			boolean exitKey = false;
			
			switch (key) {
				case MOVE_NORTH:
					position[1]--;
					break;
				case MOVE_EAST:
					position[0]++;
					break;
				case MOVE_SOUTH:
					position[1]++;
					break;
				case MOVE_WEST:
					position[0]--;
					break;
				case SHOOT_NORTH:
				case SHOOT_WEST:
				case SHOOT_SOUTH:
				case SHOOT_EAST:
					if (hasArrow) {
						Direction dir = Direction.getDirectionOfAction(key);
						hitWumpus = board.shoot(position, dir);
					}
					hasArrow = false;
					break;
				case PICK_UP_GOLD:
					if (board.pickUpGold(position))
					{
						hasGold = true;
					}
					break;
				case EXIT:
					exitKey = true;
					break;
			}
			
			if (isStartPosition) {
				int[] max = board.getMaxPosition();
				
				// if this is the player's start position and he is:
				// exiting or
				// leaving top or
				// leaving left or
				// leaving bottom or
				// leaving right
				if (exitKey ||
				    ((startPosition[1] == 0) && (position[1] == -1)) ||
					((startPosition[0] == 0) && (position[0] == -1)) ||
					((startPosition[1] == max[1]) && (position[1] == (max[1] + 1))) ||
					((startPosition[0] == max[0]) && (position[0] == (max[0] + 1)))) {
					return null;
				}
			}
			
			if (((position[0] != currentPosition[0]) || (position[1] != currentPosition[1])) &&
			    (board.isValid(position))) {
				currentPosition = position;
				return position;
			}
		}
	}
	
	public abstract Actions getAction(String attributes);
}
